from logging import getLogger

from nevow.athena import LiveElement, expose
from nevow.flat import flatten
from nevow.loaders import stan
from nevow import tags

from zope.component import provideUtility, getUtilitiesFor, getGlobalSiteManager

from meercat.mapreduce import interfaces



__all__ = ['ReducerList']

log = getLogger('meercat.server.nevow.elements.reducer')

class ReducerList(LiveElement):
    jsClass = u'Meercat.Reducer.List'
    
    docFactory = stan(tags.div(render=tags.directive('liveElement'))[
        tags.ul(class_='ReducerListActions actionList')[
            tags.li()[
                tags.a(href='#',
                       onclick="Nevow.Athena.Widget.get(this).addReducerElement(); return false;")['Add Reducer']],
            tags.li()[
                tags.a(href='#',
                       onclick="Nevow.Athena.Widget.get(this).refresh(); return false;")['Refresh List']]],
        tags.ul(class_='ReducerList'),])
    
    def getRegistry(self):
        return getUtility(interfaces.IMapperRegistry)
    
    @expose
    def getReducerList(self):
        log.info('%s.getReducerList()' % (str(self),))
        
        return map(lambda t: {u'name':unicode(t[0]),
                              u'formats':map(unicode,t[1].getFormats()),
                              u'type': unicode(type(t[1]))},
                   getUtilitiesFor(interfaces.IReducer))
    
    @expose
    def deleteReducer(self, name):
        log.info('%s.deleteReducer(name=%s)' % (str(self),name))
        
        getGlobalSiteManager().unregisterUtility(provided=interfaces.IReducer,
                                                 name=name)
        
        return True
    
    @expose
    def getAddReducerElement(self):
        log.info('%s.getAddReducerElement()' % (str(self),))
        #e = MapperTypeForm()
        #e.setFragmentParent(self)
        #return e

"""
class MapperTypeForm(LiveElement):
    jsClass = u'Meercat.Mapper.Types'
    
    @property
    def types(self):
        return {'MARC21 to XML': MarcXmlMapperForm,
                'XSLT': XslMapperForm,}
    
    @property
    def docFactory(self):
        return stan(tags.div(class_='yui-g',
                             render=tags.directive('liveElement'))[
        tags.h1()['Add Mapper'],
        tags.a(href='#',onclick='Nevow.Athena.Widget.get(this).remove(); return false;')['Close'],
        tags.div(class_='mapperTypeForm')[
            tags.h2()['Select Mapper Type'],
                tags.form()[
                    tags.ul()[
                        tags.li()[tags.select(name='type',
                                              onchange="Nevow.Athena.Widget.get(this).selectType();")[
                            tags.option(value='')['Select Mapper Type'],
                            map(lambda x: tags.option(value=x)[x],
                                sorted(self.types.keys()))]]]]]])
    
    @expose
    def getMapperForm(self, type):
        log.info('%s.getMapperForm(type=%s)' % (str(self), type))
        if not type:
            return False
        
        if not type in self.types:
            raise ValueError('Unkown mapper type')
        
        form = self.types[type]()
        form.setFragmentParent(self)
        
        return form

class MapperForm(LiveElement):
    jsClass = u'Meercat.Mapper.Form'
    
    formatCount = 0
    
    @property
    def docFactory(self):
        return stan(tags.div(class_='mapperForm',
                             render=tags.directive('liveElement'))[
            tags.form()[
                tags.ul()[
                    self.getFields(),
                    tags.input(value="Add Mapper", type="button",
                               onclick="Nevow.Athena.Widget.get(this).submit();",)]]])
    
    def getFields(self):
        log.info('%s.getFields()' % (str(self),))
        return [tags.li(_class='mapperFormats')['Formats:',self.getFormatInput(),
                                                self.getFormatInput(),
                                                tags.a(href='#',onclick='Nevow.Athena.Widget.get(this).addFormatInput(); return false;')['Add another format']]]
    
    def getFormatInput(self):
        self.formatCount += 1
        
        return tags.div()[
            tags.input(type='text',name='formatSource%s' % (self.formatCount,)),
            tags.input(type='text',name='formatTarget%s' % (self.formatCount,))]
    
    @expose
    def getFlatFormatInput(self):
        return unicode(flatten(self.getFormatInput()))
    
    def cleanFormatInput(self, data):
        data['formats'] = []
        
        for i in range(1,self.formatCount+1):
            format = (data.pop('formatSource%s' % (i,),'').strip(),
                      data.pop('formatTarget%s' % (i,),'').strip(),)
            
            if format[0] and format[1]:
                data['formats'].append(format)
        
        return data
    
    @expose
    def submit(self, **data):
        log.info('%s.submit(%s)' % (str(self),str(data)))
        
        data = self.cleanFormatInput(data)
        
        return getUtility(interfaces.IMapperRegistry).register(self._createMapper(data))

class MarcXmlMapperForm(MapperForm):
    def _createMapper(self, data):
        from meercat.mapreduce.mappers.marc import Marc21ToMarcXmlMapper
        
        formats = None
        
        if 'formats' in data and len(data['formats']) > 0:
            formats = data['formats']
        
        return Marc21ToMarcXmlMapper(formats)

class XslMapperForm(MapperForm):
    def getFields(self):
        log.info('%s.getFields()' % (str(self),))
        fields = [tags.li()['Stylesheet: ',
        
                            tags.input(type='text',name='stylesheet')]]
        fields.extend(super(XslMapperForm, self).getFields())
        return fields
    
    def _createMapper(self, data):
        if not 'formats' in data or len(data['formats']) == 0:
            raise ValueError('Formats are required')
        
        data['stylesheet'] = moduleReplace(data['stylesheet'].strip())
        log.info('stylesheet: %s' % (str(data['stylesheet'])))
        from meercat.mapreduce.mappers.xsl import XslMapper
        
        return XslMapper(*map(lambda t: (t[0],t[1],data['stylesheet']),
                              data['formats']))
"""